package com.iogame.iogamevalidatortest;

import com.iohao.game.action.skeleton.core.CmdKit;
import com.iohao.game.action.skeleton.core.flow.codec.ProtoDataCodec;
import com.iohao.game.bolt.broker.client.external.bootstrap.message.ExternalMessage;
import com.iohao.game.common.kit.ProtoKit;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Optional;

@Slf4j
public class WebSocketClientConnector {

    private String wsUrl;

    private WebSocketClient webSocketClient;

    public WebSocketClientConnector(String wsUrl) {
        this.wsUrl = wsUrl;
    }


    protected void connect() throws Exception {
        log.info("开始连接{}", wsUrl);
        webSocketClient = new DemoWebSocketClient(this, new URI(wsUrl), new Draft_6455());
        webSocketClient.connect();
    }

    /**
     * 向服务器发起请求
     *
     * @param cmd
     * @param subCmd
     * @param requestObj
     */
    public void request(int cmd, int subCmd, Object requestObj) {
        ExternalMessage externalMessage = new ExternalMessage();
        // 请求命令类型: 0 心跳，1 业务
        externalMessage.setCmdCode(1);
        // 路由
        externalMessage.setCmdMerge(cmd, subCmd);
        if (requestObj != null) {
            // 业务数据
            byte[] data = ProtoDataCodec.me().encode(requestObj);
            externalMessage.setData(data);
        }
        log.info("发送请求({},{})：{}", cmd, subCmd, externalMessage);
        request(externalMessage);
    }

    protected void request(ExternalMessage externalMessage) {
        byte[] bytes = ProtoKit.toBytes(externalMessage);
        webSocketClient.send(bytes);
    }

    @Setter
    private IResponse response;

    @Slf4j
    static class DemoWebSocketClient extends WebSocketClient {
        private WebSocketClientConnector clientConnector;

        public DemoWebSocketClient(WebSocketClientConnector clientConnector, URI serverUri, Draft protocolDraft) {
            super(serverUri, protocolDraft);
            this.clientConnector = clientConnector;
        }

        @Override
        public void onOpen(ServerHandshake serverHandshake) {
            log.info("连接{}成功", clientConnector.wsUrl);
        }

        @Override
        public void onMessage(String s) {

        }

        @Override
        public void onClose(int i, String s, boolean b) {
            log.info("连接关闭");
        }

        @Override
        public void onError(Exception e) {
            log.error("通讯异常", e);
        }

        @Override
        public void onMessage(ByteBuffer byteBuffer) {
            // 接收服务器返回的消息
            byte[] dataContent = byteBuffer.array();
            ExternalMessage message = ProtoKit.parseProtoByte(dataContent, ExternalMessage.class);
            if (message.getCmdCode() == 0) {
                return;
            }
            int cmd = CmdKit.getCmd(message.getCmdMerge());
            int subCmd = CmdKit.getSubCmd(message.getCmdMerge());
            log.info("收到消息{},{} ExternalMessage ========== \n{}", cmd, subCmd, message);

            if (message.getResponseStatus() != 0) {
                return;
            }
            byte[] data = message.getData();

            Optional.of(clientConnector.response).ifPresent(c -> {
                c.response(cmd, subCmd, data);
            });
        }
    }
}
